from layer import layer
from camera import camera
from gameflags import *
from OpenGL.GL import *
import Image, random

class world:
    def __init__(self):
        self.layers = []
        self.meshes= []
        self.size = []
        self.camera = camera()
        self.textures = {}
        self.tex_pend = []
    def newLayer(self):
        self.layers.append(layer(self.size))
        
    def addMesh(self, meshes):
        self.meshes.append(meshes)
        
    def processEvent(self,event):
        for mesh in self.meshes:
            if mesh.selected:
                #event.GetKeyCode()
                for definition in mesh.events:
                    definition(event.GetKeyCode())

    def storeTexture(self,filename):
        self.filename = filename

    def allocateTextures(self):
        for filename in self.tex_pend:
            image = Image.open(filename)
            (w,h) = image.size
            image = image.tostring("raw", "RGBX", 0, -1)
            ## Bind texture into memory
            self.textures[filename] = glGenTextures(1)
            glBindTexture(GL_TEXTURE_2D, self.textures[filename])
            glPixelStorei(GL_UNPACK_ALIGNMENT,1)
            glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE,  image)
            #gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,GL_RGB, GL_UNSIGNED_BYTE, image );
            
            print "Texture binded: ",glGetIntegerv(GL_TEXTURE_BINDING_2D)
        self.tex_pend = []
        
    def bindTexture(self,filename):
        self.tex_pend.append(filename)
        
    def render(self, mode=RENDER_WORLD):
        ## Bind any new incoming textures
        self.allocateTextures()
        
        ## Terrain Render Impliments
        
        ## Mesh Render Impliments
        for mesh in self.meshes:
            ##Pre-compile mesh if not init'd
            if mesh.displayID == None:
                mesh.displayID = glGenLists(1)
                glNewList(mesh.displayID,GL_COMPILE)
                print "Compiling:",mesh.name
                
                if POLYGONS in mesh.renderType:
                    glColor3f(1.0, 1.0, 1.0)
                    if mesh.faces[0].textureID != None:
                        glEnable(GL_TEXTURE_2D)
                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
                        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
                        glBindTexture(GL_TEXTURE_2D, self.textures[mesh.faces[0].textureID])
                        #print "Texture binded: ",glGetIntegerv(GL_TEXTURE_BINDING_2D)
                        if not glIsTexture(self.textures[mesh.faces[0].textureID]):
                            print "Error: texture not binded - Texture ID:",mesh.faces[0].textureID
                        glEnable(GL_CULL_FACE)
                        
                    #glEnable(GL_CULL_FACE)
                    glBegin(GL_TRIANGLES)
                    for face in mesh.faces:
                        for vIndex in face.mapping:
                            (x,y,z) = mesh.vertices[vIndex]
                            if len(mesh.vertices[vIndex].uv):
                                (s,t  ) = mesh.vertices[vIndex].uv[0]
                                glTexCoord2f( s, t )
                            glVertex3f( x, y, z )
                    glEnd()
                    
                    if mesh.faces[0].textureID != None:
                        glDisable(GL_CULL_FACE)
                        glDisable(GL_TEXTURE_2D)
                    
                if EDGES in mesh.renderType:
                    glColor3f(0.0, 0.0, 0.0)
                    glDisable(GL_CULL_FACE)
                    glBegin(GL_LINES)
                    for face in mesh.faces:
                        (v1,v2,v3) = face.mapping
                        v1 = mesh.vertices[v1]; v2 = mesh.vertices[v2]; v3 = mesh.vertices[v3]
                        glVertex3f(v1[0],v1[1],v1[2])
                        glVertex3f(v2[0],v2[1],v2[2])
                        glVertex3f(v2[0],v2[1],v2[2])
                        glVertex3f(v3[0],v3[1],v3[2])
                        glVertex3f(v3[0],v3[1],v3[2])
                        glVertex3f(v1[0],v1[1],v1[2])
                    glEnd()
                
                if POINTS in mesh.renderType:
                    glPointSize(10.0)
                    glColor3f(1.0, 1.0, 0)
                    glBegin(GL_POINTS)
                    for vertex in mesh.vertices:
                        glVertex3f(vertex[0],vertex[1],vertex[2])
                    glEnd()
                    
                
                print "Done"
                glEndList()
            ## Render Mesh
            if mode == RENDER_PICKY:
                glDisable(GL_DITHER)
                
            glPushMatrix()
            
            glTranslatef(mesh.position[0], mesh.position[1], mesh.position[2])
            glRotatef(mesh.rotation[0], 1.0,  0  ,   0)
            glRotatef(mesh.rotation[1], 0  ,  1.0,   0)
            glRotatef(mesh.rotation[2], 0  ,  0  , 1.0)
            glScalef(mesh.scale[0], mesh.scale[1], mesh.scale[2])
            
            if mode == RENDER_PICKY:
                ## Render unique color for mesh
                (r,g,b) = random.random(), random.random(), random.random()
                (r,g,b) = 0.5,0.5,0.5
                mesh.pickyCol = [r,g,b]
                glColor3f(r,g,b)
                glBegin(GL_TRIANGLES)
                for face in mesh.faces:
                    for vIndex in face.mapping:
                        (x,y,z) = mesh.vertices[vIndex]
                        glVertex3f( x, y, z )
                glEnd()
            else:
                glCallList(mesh.displayID)
            
            glPopMatrix()
            
            if mode == RENDER_PICKY:
                glEnable(GL_DITHER)
                